package cn.xyz.mianshi.service.impl;



import java.lang.reflect.Array;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.xyz.commons.ex.ServiceException;
import cn.xyz.mianshi.vo.*;
import com.mongodb.client.MongoCollection;
import org.apache.rocketmq.client.producer.SendResult;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.query.Query;
import org.mongodb.morphia.query.UpdateOperations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.google.common.collect.Maps;


import cn.xyz.commons.constants.KConstants;
import cn.xyz.commons.constants.KConstants.PayResultCode;
import cn.xyz.commons.support.Callback;
import cn.xyz.commons.utils.DateUtil;
import cn.xyz.commons.utils.ReqUtil;
import cn.xyz.commons.utils.StringUtil;
import cn.xyz.commons.utils.ThreadUtil;
import cn.xyz.commons.vo.JSONMessage;
import cn.xyz.mianshi.vo.Room.MemberRate;
import cn.xyz.mianshi.model.PageResult;
import cn.xyz.mianshi.utils.SKBeanUtils;
import cn.xyz.repository.mongo.MongoRepository;
import cn.xyz.service.KXMPPServiceImpl;
import cn.xyz.service.KXMPPServiceImpl.MessageBean;

@Service
public class RedPacketManagerImpl extends MongoRepository<RedPacket, ObjectId>{
	private static final Logger log = LoggerFactory.getLogger(RedPacketManagerImpl.class);
	@Override
	public Datastore getDatastore() {
		return SKBeanUtils.getDatastore();
	}
	@Override
	public Class<RedPacket> getEntityClass() {
		return RedPacket.class;
	}
	
	private static UserManagerImpl getUserManager(){
		UserManagerImpl userManager = SKBeanUtils.getUserManager();
		return userManager;
	};
	
	public RedPacket saveRedPacket(RedPacket entity){
			entity.setId(new ObjectId());
			save(entity);
			return entity;
	}
	private  void RedPacketGameV1(RedPacket packet)
	{
		//if(false)
		{
			double stockValue = 0.0;
			Query<StockValue> q =getDatastore().createQuery(StockValue.class).field("roomJid").equal(packet.getRoomJid());

			StockValue dbStockValue =	q.get();
			if(dbStockValue != null)
			{
				stockValue = dbStockValue.getStock();
			}
			else{
				return;
			}

			//查询个人胜率
			ObjectId roomID = SKBeanUtils.getRoomManager().getRoomId(packet.getRoomJid());
			MemberRate member = SKBeanUtils.getRoomManager().getMemberRateInfo(roomID,packet.getUserId());
			double nMemberWinRate = -1;

			stockValue += packet.getMoney();
			//红包群玩法，提前计算好结果
			int nPackCount = packet.getCount();
			String greetings = packet.getGreetings();
			boolean isNumber = false;
			List<String> betNumList = new ArrayList<String>();

			for(int i = 0 ; i < greetings.length();i++ )
			{
				String szSpStr = greetings.substring(i,i+1);
				Pattern pattern = Pattern.compile("[0-9]*");
				Matcher isNum = pattern.matcher(szSpStr);
				if( !isNum.matches() ){
					isNumber = false;
					break;
				}else{
					isNumber = true;
					for(int x=0;x<betNumList.size();x++)
					{
						if(betNumList.get(x).equals(szSpStr))
						{
							isNumber = false;
							break;
						}
					}
					if(!isNumber)
					{
						break;
					}
					betNumList.add(szSpStr);
				}
			}
			//输入错误，不进行控制
			if( !isNumber || (nPackCount != 5 && nPackCount != 6 && nPackCount != 9)) return;
			if(betNumList.size()< 2 &&  nPackCount == 9) return;
			//读取群整体胜率
			double fWinRate = dbStockValue.getWinRate();
			Random r = new Random();
			int currRate = r.nextInt(98)+1;
			//读取具体玩法胜率
			List<Double> _userWinList = new ArrayList<Double>();
			int minBomCount = 0;
			int maxBomCount = 9;
			if(betNumList.size() == 1 && nPackCount == 5)
			{
				if(currRate < member.getWinRate5())
				{
					nMemberWinRate = member.getWinRate5();
					minBomCount = 5;
					maxBomCount = 5;
				}
				else if(currRate < member.getWinRate4())
				{
					nMemberWinRate =  member.getWinRate4();
					minBomCount = 4;
					maxBomCount = 4;
				}
				else if(currRate < member.getWinRate3())
				{
					nMemberWinRate =  member.getWinRate3();
					minBomCount = 3;
					maxBomCount = 3;
				}
				else if(currRate < member.getWinRate2())
				{
					nMemberWinRate =  member.getWinRate2();
					minBomCount = 2;
					maxBomCount = 2;
				}
				else if(currRate < member.getWinRate1())
				{
					nMemberWinRate =  member.getWinRate1();
					minBomCount = 1;
					maxBomCount = 1;
				}
			}
			if(betNumList.size() > 1 && nPackCount == 5)
			{
				if(betNumList.size() == 2)
				{
					minBomCount = 2;
					maxBomCount = 9;
					nMemberWinRate = member.getWinRate6();
				}
				if(betNumList.size() == 3)
				{
					minBomCount = 3;
					maxBomCount = 9;
					nMemberWinRate = member.getWinRate7();
				}
				if(betNumList.size() == 4)
				{
					minBomCount = 4;
					maxBomCount = 9;
					nMemberWinRate = member.getWinRate8();
				}
				if(betNumList.size() == 5)
				{
					minBomCount = 5;
					maxBomCount = 9;
					nMemberWinRate = member.getWinRate9();
				}

			}
			if(betNumList.size() == 1 && nPackCount == 6)
			{
				if(fWinRate < member.getWinRate15())
				{
					nMemberWinRate = member.getWinRate15();
					minBomCount = 6;
					maxBomCount = 6;
				}
				else if(fWinRate < member.getWinRate14())
				{
					nMemberWinRate = member.getWinRate14();
					minBomCount = 5;
					maxBomCount = 5;
				}
				else if(fWinRate < member.getWinRate13())
				{
					nMemberWinRate = member.getWinRate13();
					minBomCount = 4;
					maxBomCount = 4;
				}
				else if(fWinRate < member.getWinRate12())
				{
					nMemberWinRate = member.getWinRate12();
					minBomCount = 3;
					maxBomCount = 3;
				}
				else if(fWinRate < member.getWinRate11())
				{
					nMemberWinRate = member.getWinRate11();
					minBomCount = 2;
					maxBomCount = 2;
				}
				else if(fWinRate < member.getWinRate10())
				{
					nMemberWinRate = member.getWinRate10();
					minBomCount = 1;
					maxBomCount = 1;
				}
			}
			if(betNumList.size() > 1 && nPackCount == 6)
			{
				if(betNumList.size() == 2)
				{
					minBomCount = 2;
					maxBomCount = 9;
					nMemberWinRate = member.getWinRate16();
				}
				if(betNumList.size() == 3)
				{
					minBomCount = 3;
					maxBomCount = 9;
					nMemberWinRate = member.getWinRate17();
				}
				if(betNumList.size() == 4)
				{
					minBomCount = 4;
					maxBomCount = 9;
					nMemberWinRate = member.getWinRate18();
				}
				if(betNumList.size() == 5)
				{
					minBomCount = 5;
					maxBomCount = 9;
					nMemberWinRate = member.getWinRate19();
				}
				if(betNumList.size() == 6)
				{
					minBomCount = 6;
					maxBomCount = 9;
					nMemberWinRate = member.getWinRate20();
				}

			}
			if(betNumList.size() ==2 && nPackCount == 9)
			{

				if(currRate < member.getWinRate25())
				{
					nMemberWinRate = member.getWinRate25();
					minBomCount = 9;
					maxBomCount = 9;
				}
				else if(currRate < member.getWinRate24())
				{
					nMemberWinRate = member.getWinRate24();
					minBomCount = 8;
					maxBomCount = 8;
				}
				else if(currRate < member.getWinRate23())
				{
					nMemberWinRate = member.getWinRate23();
					minBomCount = 7;
					maxBomCount = 7;
				}
				else if(currRate < member.getWinRate22())
				{
					nMemberWinRate = member.getWinRate22();
					minBomCount = 6;
					maxBomCount = 6;
				}
				else if(currRate < member.getWinRate21())
				{
					nMemberWinRate = member.getWinRate21();
					minBomCount = 1;
					maxBomCount = 5;
				}
			}
			if(betNumList.size() ==3 && nPackCount == 9)
			{

				if(currRate < member.getWinRate29())
				{
					nMemberWinRate = member.getWinRate29();
					minBomCount = 9;
					maxBomCount = 9;
				}
				else if(currRate < member.getWinRate28())
				{
					nMemberWinRate = member.getWinRate28();
					minBomCount = 8;
					maxBomCount = 8;
				}
				else if(currRate < member.getWinRate27())
				{
					nMemberWinRate = member.getWinRate27();
					minBomCount = 7;
					maxBomCount = 7;
				}
				else if(currRate < member.getWinRate26())
				{
					nMemberWinRate = member.getWinRate26();
					minBomCount = 1;
					maxBomCount = 6;
				}
			}
			if(betNumList.size() ==4 && nPackCount == 9)
			{
				if(currRate < member.getWinRate33())
				{
					nMemberWinRate = member.getWinRate33();
					minBomCount = 9;
					maxBomCount = 9;
				}
				else if(currRate < member.getWinRate32())
				{
					nMemberWinRate = member.getWinRate32();
					minBomCount = 8;
					maxBomCount = 8;
				}
				else if(currRate < member.getWinRate31())
				{
					nMemberWinRate = member.getWinRate31();
					minBomCount = 7;
					maxBomCount = 7;
				}
				else if(currRate < member.getWinRate30())
				{
					nMemberWinRate = member.getWinRate30();
					minBomCount = 1;
					maxBomCount = 6;
				}

			}
			if(betNumList.size() ==5 && nPackCount == 9)
			{
				nMemberWinRate = member.getWinRate34();
				minBomCount = 1;
				maxBomCount = 9;
			}
			if(betNumList.size() ==6 && nPackCount == 9)
			{
				nMemberWinRate = member.getWinRate35();
				minBomCount = 1;
				maxBomCount = 9;
			}
			if(betNumList.size() ==7 && nPackCount == 9)
			{
				nMemberWinRate = member.getWinRate36();
				minBomCount = 1;
				maxBomCount = 9;
			}
			if(betNumList.size() ==8 && nPackCount == 9)
			{
				nMemberWinRate = member.getWinRate37();
				minBomCount = 1;
				maxBomCount = 9;
			}
			if(betNumList.size() ==9 && nPackCount == 9)
			{
				nMemberWinRate = member.getWinRate38();
				minBomCount = 1;
				maxBomCount = 9;
			}

			if(nMemberWinRate > -1)
			{
				fWinRate = nMemberWinRate;
			}


			List<Double> openRecord = new ArrayList<Double>();
			logger.info("[ww]currRate="+currRate+",fWinRate="+fWinRate);
			//进入控制单元
			if(currRate >= fWinRate && fWinRate > 0)
			{
				if(betNumList.size() ==1)
				{
					//单雷模式
					while (true)
					{
						openRecord.clear();
						Map<String,Double> returnMap  = getWinScoreRedPacketGameV1_single(packet,nPackCount,betNumList.get(0),openRecord);
						double userWinScore = returnMap.get("winScore");
						if(userWinScore == 0) break;
					}
				}
				else{
					//多雷模式
					while (true)
					{
						openRecord.clear();
						Map<String,Double> returnMap  = getWinScoreRedPacketGameV1_multiple(packet,nPackCount,betNumList,openRecord);
						double userWinScore = returnMap.get("winScore");
						if(userWinScore == 0) break;
					}
				}
				for(int i = 0; i < openRecord.size();i++)
				{
					RedPacketBuffer entity = new RedPacketBuffer();
					entity.setRedId(packet.getId());
					entity.setMoney(openRecord.get(i));
					getDatastore().save(entity);
				}
				if(dbStockValue != null)
				{
					UpdateOperations<StockValue> operations = getDatastore().createUpdateOperations(StockValue.class);
					operations.set("stock", stockValue);
					getDatastore().update(q, operations);
				}
				else{
					StockValue entity = new StockValue();
					entity.setRoomJid(packet.getRoomJid());
					entity.setStock(stockValue);
					getDatastore().save(entity);
				}
				return;
			}
			else if (currRate < fWinRate){
				if(betNumList.size() ==1)
				{
					//单雷模式
					int count=0;
					//确认开奖结果
					logger.info("[ww]minBomCount="+minBomCount+",maxBomCount="+maxBomCount);
					while (true)
					{
						count++;
						openRecord.clear();
						Map<String,Double> returnMap  = getWinScoreRedPacketGameV1_single(packet,nPackCount,betNumList.get(0),openRecord);
						double userWinScore = returnMap.get("winScore");
						if(userWinScore > 0 && stockValue >userWinScore && minBomCount <=  returnMap.get("winCount") && maxBomCount >= returnMap.get("winCount")){
							stockValue -= userWinScore;
							break;
						}
						if(count > 200 && userWinScore<=0)
						{
							break;
						}
					}
				}
				else{
					//多雷模式
					int count=0;
					while (true)
					{
						count++;
						openRecord.clear();
						Map<String,Double> returnMap = getWinScoreRedPacketGameV1_multiple(packet,nPackCount,betNumList,openRecord);
						double userWinScore = returnMap.get("winScore");
						if(userWinScore > 0 && stockValue >userWinScore && minBomCount <=  returnMap.get("winCount") && maxBomCount >= returnMap.get("winCount")){
							stockValue -= userWinScore;
							break;
						}
						if(count > 200 && userWinScore<=0)
						{
							break;
						}
					}
				}
				for(int i = 0; i < openRecord.size();i++)
				{
					RedPacketBuffer entity = new RedPacketBuffer();
					entity.setRedId(packet.getId());
					entity.setMoney(openRecord.get(i));
					getDatastore().save(entity);
				}
				if(dbStockValue != null)
				{
					UpdateOperations<StockValue> operations = getDatastore().createUpdateOperations(StockValue.class);
					operations.set("stock", stockValue);
					getDatastore().update(q, operations);
				}
				else{
					StockValue entity = new StockValue();
					entity.setRoomJid(packet.getRoomJid());
					entity.setStock(stockValue);
					getDatastore().save(entity);
				}
				return;
			}
			//查看是否满足库存

			if(betNumList.size() ==1)
			{
				//单雷模式
				while (true)
				{
					openRecord.clear();
					Map<String,Double> returnMap = getWinScoreRedPacketGameV1_single(packet,nPackCount,betNumList.get(0),openRecord);
					double userWinScore = returnMap.get("winScore");
					if(stockValue > userWinScore ){
						stockValue -= userWinScore;
						break;
					}
				}

			}
			else{
				//多雷模式
				while (true)
				{
					openRecord.clear();
				   Map<String,Double> returnMap = getWinScoreRedPacketGameV1_multiple(packet,nPackCount,betNumList,openRecord);
					double userWinScore = returnMap.get("winScore");
					if(stockValue > userWinScore ){
						stockValue -= userWinScore;
						break;
					}
				}
			}
			for(int i = 0; i < openRecord.size();i++)
			{
				RedPacketBuffer entity = new RedPacketBuffer();
				entity.setRedId(packet.getId());
				entity.setMoney(openRecord.get(i));
				getDatastore().save(entity);
			}
			if(dbStockValue != null)
			{
				UpdateOperations<StockValue> operations = getDatastore().createUpdateOperations(StockValue.class);
				operations.set("stock", stockValue);
				getDatastore().update(q, operations);
			}
			else{
				StockValue entity = new StockValue();
				entity.setRoomJid(packet.getRoomJid());
				entity.setStock(stockValue);
				getDatastore().save(entity);
			}
			return;
 		}
	}
	//单雷
	private  Map<String,Double> getWinScoreRedPacketGameV1_single(RedPacket packet,int count,String betNumber,List<Double> openRecord)
	{
			Double OverScore = packet.getMoney();
			String szResult = "";
			for(int  i = 0; i < count ; i++)
			{
				Double dbScore = getRandomMoney(count-i, OverScore);
				openRecord.add(dbScore);
				DecimalFormat df2=new DecimalFormat("#.00");
				String szdbScore = df2.format(dbScore);

				szResult += szdbScore.substring(szdbScore.length()-1,szdbScore.length());
				OverScore -= dbScore;

			}

			//计算结果,查看包含了多少个
			int winCount = searchCount(betNumber,szResult);

			double multiple = 0;
			if(1 == winCount)
			{
				if(count == 5)
				{
					multiple = 2;
				}
				else if(count == 6)
				{
					multiple =1.6;
				}
			}
			else if(2 == winCount)
			{
				if(count == 5)
				{
					multiple = 3.3;
				}
				else if(count == 6)
				{
					multiple =3;
				}
			}
			else if(3 == winCount)
			{
				if(count == 5)
				{
					multiple = 5;
				}
				else if(count == 6)
				{
					multiple =4.5;
				}
			}
			else if(4 == winCount)
			{
				if(count == 5)
				{
					multiple = 10;
				}
				else if(count == 6)
				{
					multiple =6;
				}
			}
			else if(5 == winCount)
			{
				if(count == 5)
				{
					multiple = 15;
				}
				else if(count == 6)
				{
					multiple =12;
				}
			}
			else if(6 == winCount)
			{
				if(count == 6)
				{
					multiple =20;
				}
			}
			Map<String,Double> resultMap=Maps.newHashMap();
			resultMap.put("winCount",Double.parseDouble(String.valueOf(winCount)));
			resultMap.put("winScore", multiple * packet.getMoney());
			return resultMap;
	}

	private  	Map<String,Double> getWinScoreRedPacketGameV1_multiple(RedPacket packet,int count,List<String> betNumList,List<Double> openRecord)
	{
		Double OverScore = packet.getMoney();
		String szResult = "";
		for(int  i = 0; i < count ; i++)
		{
			Double dbScore = getRandomMoney(count-i, OverScore);
			openRecord.add(dbScore);
			DecimalFormat df2=new DecimalFormat("#.00");
			String szdbScore = df2.format(dbScore);
			szResult += szdbScore.substring(szdbScore.length()-1,szdbScore.length());
			OverScore -= dbScore;
		}
		int bomCount = 0;

		//手气最佳，免死
		Double maxScore = 0.0;
		for(int i = 0 ; i < openRecord.size();i++)
		{
			if(maxScore < openRecord.get(i) )
			{
				maxScore =openRecord.get(i);
			}
		}
		DecimalFormat df2=new DecimalFormat("#.00");
		String szMaxScore = df2.format(maxScore);
		String szMaxResult = szMaxScore.substring(szMaxScore.length()-1,szMaxScore.length());

		for(int i = 0 ;i <betNumList.size();i++)
		{
			int winCount = searchCount(betNumList.get(i),szResult);
			bomCount += winCount;
			if(szMaxResult.equals(betNumList.get(i)))
			{
				bomCount--;
			}
			if(winCount == 0) {
				Map<String,Double> resultMap=Maps.newHashMap();
				resultMap.put("winCount",0.0);
				resultMap.put("winScore",0.0);
				return resultMap;
			}
		}
		double multiple = 0;
		if(count == 5)
		{
			if(betNumList.size() ==2)
			{
				multiple  =4;
			}
			if(betNumList.size() ==3)
			{
				multiple  =20.5;
			}
			if(betNumList.size() ==4)
			{
				multiple  =40;
			}
			if(betNumList.size() ==5)
			{
				multiple  =60;
			}
		}
		else if(count == 6)
		{
			if(betNumList.size() ==2)
			{
				multiple  =3;
			}
			if(betNumList.size() ==3)
			{
				multiple  =12.8;
			}
			if(betNumList.size() ==4)
			{
				multiple  =30;
			}
			if(betNumList.size() ==5)
			{
				multiple  =60;
			}
			if(betNumList.size() ==6)
			{
				multiple  =80;
			}
		}
		else if(count == 9)
		{
			if(betNumList.size() ==2)
			{
				multiple  =1.02;
				if(bomCount==6)
				{
					multiple = multiple * 6;
				}
				else if(bomCount==7)
				{
					multiple = multiple * 7 * 2;
				}
				else if(bomCount==8)
				{
					multiple = multiple * 8 * 3;
				}
				else if(bomCount==9)
				{
					multiple = multiple * 9 * 4;
				}
			}
			if(betNumList.size() ==3)
			{
				multiple  =1.25;
				if(bomCount==7)
				{
					multiple = multiple * 7 ;
				}
				else if(bomCount==8)
				{
					multiple = multiple * 8 * 2;
				}
				else if(bomCount==9)
				{
					multiple = multiple * 9 * 3;
				}
			}
			if(betNumList.size() ==4)
			{
				multiple  =1.75;
				if(bomCount==7)
				{
					multiple = multiple * 7 ;
				}
				else if(bomCount==8)
				{
					multiple = multiple * 8 * 2;
				}
				else if(bomCount==9)
				{
					multiple = multiple * 9 * 3;
				}
			}
		}
		Map<String,Double> resultMap=Maps.newHashMap();
		resultMap.put("winCount",Double.parseDouble(String.valueOf(bomCount)));
		resultMap.put("winScore", multiple * packet.getMoney());
		return resultMap;

	}

	// 定义searchCount方法，来返回字符串出现的个数
	private  int searchCount(String shortStr, String longStr) {
		// 定义一个count来存放字符串出现的次数
		int count = 0;
		// 调用String类的indexOf(String str)方法，返回第一个相同字符串出现的下标
		while (longStr.indexOf(shortStr) != -1) {
			// 如果存在相同字符串则次数加1
			count++;
			// 调用String类的substring(int beginIndex)方法，获得第一个相同字符出现后的字符串
			longStr = longStr.substring(longStr.indexOf(shortStr)
					+ shortStr.length());
		}
		// 返回次数
		return count;
	}
	public Object sendRedPacket(int userId,RedPacket packet) {
		packet.setUserId(userId);
		packet.setUserName(SKBeanUtils.getUserManager().getNickName(userId));
		packet.setOver(packet.getMoney());
		long cuTime=DateUtil.currentTimeSeconds();
		packet.setSendTime(cuTime);
		packet.setOutTime(cuTime+KConstants.Expire.DAY1);
		Object data=saveRedPacket(packet);
		if(packet.getMoney()<0){
			throw new ServiceException(KConstants.PayResultCode.InsufficientBalance);
		}
		//修改金额
		Double balance = SKBeanUtils.getUserManager().rechargeUserMoeny(userId, packet.getMoney(), KConstants.MOENY_REDUCE);
		//红包游戏
		RedPacketGameV1(packet);


		//开启一个线程 添加一条消费记录

		ThreadUtil.executeInThread((Callback) obj -> {
			String tradeNo=StringUtil.getOutTradeNo();
			//创建充值记录
			ConsumeRecord record=new ConsumeRecord();
			record.setUserId(userId);
			record.setToUserId(packet.getToUserId());
			record.setTradeNo(tradeNo);
			record.setMoney(packet.getMoney());
			record.setStatus(KConstants.OrderStatus.END);
			record.setType(KConstants.ConsumeType.SEND_REDPACKET);
			record.setPayType(KConstants.PayType.BALANCEAY); //余额支付
			record.setDesc("红包发送");
			record.setTime(DateUtil.currentTimeSeconds());
			record.setRedPacketId(packet.getId());
			record.setOperationAmount(packet.getMoney());
			record.setCurrentBalance(balance);
			SKBeanUtils.getConsumeRecordManager().save(record);
		});
		
		return data;
	}
	
	public  JSONMessage getRedPacketById(Integer userId,ObjectId id){
		RedPacket packet=get(id);
		if(null==packet)
			return JSONMessage.failureByErrCode(KConstants.ResultCode.DataNotExists);
		Map<String,Object> map=Maps.newHashMap();
		map.put("packet", packet);
		//判断红包是否超时
		if(DateUtil.currentTimeSeconds()>packet.getOutTime()){
			map.put("list", getRedReceivesByRedId(packet.getId()));
			return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacket_TimeOut, map);
		}
			
		//判断红包是否已领完
		if(packet.getCount()>packet.getReceiveCount()){
			//判断当前用户是否领过该红包
			if(null==packet.getUserIds()||!packet.getUserIds().contains(userId)){
				map.put("list", getRedReceivesByRedId(packet.getId()));
				return JSONMessage.success(map);
			}else {
				map.put("list", getRedReceivesByRedId(packet.getId()));
				return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacketReceived, map);
			}
		}else{//红包已经领完了
			map.put("list", getRedReceivesByRedId(packet.getId()));
			return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacket_NoMore, map);
		}
	}
	
	
	
	public synchronized JSONMessage openRedPacketById(Integer userId,ObjectId id){
		RedPacket packet=get(id);
		if(null==packet)
			return JSONMessage.failureByErrCode(KConstants.ResultCode.DataNotExists);
		Map<String,Object> map=Maps.newHashMap();
		map.put("packet", packet);
		//判断红包是否超时
		if(DateUtil.currentTimeSeconds()>packet.getOutTime()){
			map.put("list", getRedReceivesByRedId(packet.getId()));
			return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacket_TimeOut,map);
		}
		//判断红包是否已领完
		if(packet.getCount()>packet.getReceiveCount()){
			//判断当前用户是否领过该红包
			//
			if(null==packet.getUserIds()||!packet.getUserIds().contains(userId)){
				packet=openRedPacket(userId, packet);
				map.put("packet", packet);
				map.put("list", getRedReceivesByRedId(packet.getId()));
				return JSONMessage.success(map);
			}
			else {
				map.put("list", getRedReceivesByRedId(packet.getId()));
				return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacketReceived, map);
			}
		}else{ //你手太慢啦  已经被领完了
			map.put("list", getRedReceivesByRedId(packet.getId()));
			return JSONMessage.failureByErrCodeAndData(PayResultCode.RedPacket_NoMore, map);
		}
	}
	
	private synchronized RedPacket openRedPacket(Integer userId,RedPacket packet){
		int overCount= packet.getCount()-packet.getReceiveCount();
		User user=getUserManager().getUser(userId);
		Double money=0.0;
		//普通红包
		if(1==packet.getType()){
			if(1==packet.getCount()-packet.getReceiveCount()){
				//剩余一个  领取剩余红包
				money=packet.getOver();
			}else{
				money=packet.getMoney()/packet.getCount();
				//保留两位小数
				DecimalFormat df = new DecimalFormat("#.00");
				money= Double.valueOf(df.format(money));
			}
		}
		else  //拼手气红包或者口令红包
		{
			log.info("[ww]:packet.getTagUserID()="+packet.getTagUserID());
			//查看是否存在预设金额
			Query<RedPacketBuffer> q =getDatastore().createQuery(RedPacketBuffer.class).field("redId").equal(packet.getId());

			RedPacketBuffer redPacketBuffer =	q.get();
			if(redPacketBuffer != null)
			{
				money = redPacketBuffer.getMoney();
				getDatastore().delete(getDatastore().createQuery(RedPacketBuffer.class).field("_id").equal(redPacketBuffer.getId()));
			}
			else{
				money=getRandomMoney(overCount, packet.getOver());
			}

		}
			
			// 保留两位小数
			Double over=(packet.getOver()-money);
			DecimalFormat df = new DecimalFormat("#.00");
			packet.setOver(Double.valueOf(df.format(over)));
			packet.getUserIds().add(userId);
			UpdateOperations<RedPacket> ops=createUpdateOperations();
			ops.set("receiveCount", packet.getReceiveCount()+1);
			ops.set("over",packet.getOver());
			ops.set("userIds", packet.getUserIds());
			if(0==packet.getOver()){
				ops.set("status", 2);
				packet.setStatus(2);
			}
				updateAttributeByOps(packet.getId(), ops);
			
			
		//实例化一个红包接受对象
		RedReceive receive=new RedReceive();
			receive.setMoney(money);
			receive.setUserId(userId);
			receive.setSendId(packet.getUserId());
			receive.setRedId(packet.getId());
			receive.setTime(DateUtil.currentTimeSeconds());
			receive.setUserName(getUserManager().getUser(userId).getNickname());
			receive.setSendName(getUserManager().getUser(packet.getUserId()).getNickname());
			ObjectId id=(ObjectId) getDatastore().save(receive).getId();
			receive.setId(id);

			if(money<0){
				throw new ServiceException(KConstants.PayResultCode.InsufficientBalance);
			}
			//修改金额
		    Double balance = getUserManager().rechargeUserMoeny(userId, money, KConstants.MOENY_ADD);
		    final Double num=money;
			MessageBean messageBean=new MessageBean();
			messageBean.setType(KXMPPServiceImpl.OPENREDPAKET);
			messageBean.setFromUserId(user.getUserId().toString());
			messageBean.setFromUserName(user.getNickname());
			if(packet.getRoomJid()!=null){
				messageBean.setObjectId(packet.getRoomJid());
				if(0==packet.getOver()) {
					messageBean.setFileSize(1);
					messageBean.setFileName(packet.getSendTime()+"");
				}
				messageBean.setRoomJid(packet.getRoomJid());
			}
			messageBean.setMsgType(null == packet.getRoomJid() ? 0 : 1);
			messageBean.setContent(packet.getId().toString());
		if(packet.getRoomJid()!=null){
			messageBean.setToUserId(packet.getRoomJid());
		}
		else {
			messageBean.setToUserId(packet.getUserId()+"");
		}

			messageBean.setToUserName(getUserManager().getNickName(packet.getUserId()));
			messageBean.setMessageId(StringUtil.randomUUID());
			try {
				KXMPPServiceImpl.getInstance().send(messageBean);
			} catch (Exception e) {
				e.printStackTrace();
			}
			//开启一个线程 添加一条消费记录
			ThreadUtil.executeInThread(new Callback() {
				
				@Override
				public void execute(Object obj) {
					String tradeNo=StringUtil.getOutTradeNo();
					//创建充值记录
					ConsumeRecord record=new ConsumeRecord();
					record.setUserId(userId);
					record.setToUserId(packet.getUserId());
					record.setTradeNo(tradeNo);
					record.setMoney(num);
					record.setStatus(KConstants.OrderStatus.END);
					record.setType(KConstants.ConsumeType.RECEIVE_REDPACKET);
					record.setPayType(KConstants.PayType.BALANCEAY); //余额支付
					record.setDesc("红包接收");
					record.setOperationAmount(num);
					record.setCurrentBalance(balance);
					record.setRedPacketId(packet.getId());
					record.setTime(DateUtil.currentTimeSeconds());
					SKBeanUtils.getConsumeRecordManager().save(record);
				}
			});
		return packet;
	}
	//发送领取红包消息  即 添加消费记录
	public void sendOpenMessageAndCreateRecord() {
		
	}
	
	private synchronized Double getRandomMoney(int remainSize,Double remainMoney) {
		    // remainSize 剩余的红包数量
		    // remainMoney 剩余的钱
			Double money=0.0;
		    if (remainSize == 1) {
		        remainSize--;
		         money=(double) Math.round(remainMoney * 100) / 100;
		         System.out.println("=====> "+money);
	            return money;
		    }
		    Random r     = new Random();
		    double min   = 0.01; //
		    double max   = remainMoney / remainSize * 2;
		     money = r.nextDouble() * max;
		    money = money <= min ? 0.01: money;
		    money = Math.floor(money * 100) / 100;
		    System.out.println("=====> "+money);
		    remainSize--;
		    remainMoney -= money;
		    DecimalFormat df = new DecimalFormat("#.00");
		   return Double.valueOf(df.format(money));
	}
	
	public void replyRedPacket(String id,String reply) {
		Integer userId = ReqUtil.getUserId();
		Query query=getDatastore().createQuery(RedReceive.class).field("userId").equal(userId);
		query.filter("redId", new ObjectId(id));
		UpdateOperations<RedReceive> operations = getDatastore().createUpdateOperations(RedReceive.class);
		operations.set("reply", reply);
		getDatastore().update(query, operations);
	}
	
	//根据红包Id 获取该红包的领取记录
	public  List<RedReceive> getRedReceivesByRedId(ObjectId redId){
		return (List<RedReceive>) getEntityListsByKey(RedReceive.class, "redId", redId,"-time");
	}
	//发送的红包
	public List<RedPacket> getSendRedPacketList(Integer userId,int pageIndex,int pageSize){
		Query<RedPacket> q=createQuery().field("userId").equal(userId);
		return q.order("-sendTime").offset(pageIndex*pageSize).limit(pageSize).asList();
	}
	//收到的红包
	public List<RedReceive> getRedReceiveList(Integer userId,int pageIndex,int pageSize){
		return (List<RedReceive>) getEntityListsByKey(RedReceive.class, "userId", userId, "-time", pageIndex, pageSize);
	}
	
	
	//发送的红包
	public PageResult<RedPacket> getRedPacketList(String userName,int pageIndex,int pageSize,String redPacketId){
		PageResult<RedPacket> result = new PageResult<RedPacket>();
		Query<RedPacket> q=createQuery().order("-sendTime");
		if(!StringUtil.isEmpty(userName))
			q.field("userName").equal(userName);
		if(!StringUtil.isEmpty(redPacketId))
			q.field("_id").equal(new ObjectId(redPacketId));
		result.setCount(q.count());
		result.setData(q.asList(pageFindOption(pageIndex, pageSize, 1)));
		return result;
	}
	
	//发送的红包
	public PageResult<RedReceive> receiveWater(String redId,int pageIndex,int pageSize){
		PageResult<RedReceive> result = new PageResult<RedReceive>();
		Query<RedReceive> q=getDatastore().createQuery(RedReceive.class).field("redId").equal(new ObjectId(redId)).order("-time");
		result.setCount(q.count());
		result.setData(q.asList(pageFindOption(pageIndex, pageSize, 1)));
		return result;
	}
}
